package com.kyh.util.sftp;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

import org.apache.commons.io.IOUtils;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;
import com.kyh.util.DESUtil;
import com.kyh.util.qiniucloud.QiniuCloudUtil;


/**
 * 类说明 sftp工具类
 */
public class SftpUtil {
    private static SftpUtil me = new SftpUtil();
    private ChannelSftp sftp;

    private Session session;
    /** SFTP 登录用户名*/
    private String username;
    /** SFTP 登录密码*/
    private String password;
    /** 私钥 */
    private String privateKey;
    /** SFTP 服务器地址IP地址*/
    private String host;
    /** SFTP 端口*/
    private int port;


    /**
     * 构造基于密码认证的sftp对象  
     */
    public SftpUtil(String username, String password, String host, int port) {
        this.username = username;
        this.password = password;
        this.host = host;
        this.port = port;
    }

    /**
     * 构造基于秘钥认证的sftp对象 
     */
    public SftpUtil(String username, String host, int port, String privateKey) {
        this.username = username;
        this.host = host;
        this.port = port;
        this.privateKey = privateKey;
    }

    public SftpUtil(){}


    /**
     * 连接sftp服务器 
     */
    public void login(){
        try {
            JSch jsch = new JSch();
            if (privateKey != null) {
                jsch.addIdentity(privateKey);// 设置私钥  
            }

            session = jsch.getSession(username, host, port);

            if (password != null) {
                session.setPassword(password);
            }
            
//            Properties config = new Properties();
//            config.put("StrictHostKeyChecking", "no");
//            session.setConfig(config);
            session.setConfig("StrictHostKeyChecking", "no");
            
            session.connect();

            Channel channel = session.openChannel("sftp");
            channel.connect();

            sftp = (ChannelSftp) channel;
        } catch (JSchException e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭连接 server  
     */
    public void logout(){
        if (sftp != null) {
            if (sftp.isConnected()) {
                sftp.disconnect();
            }
        }
        if (session != null) {
            if (session.isConnected()) {
                session.disconnect();
            }
        }
    }


    /**
     * 将输入流的数据上传到sftp作为文件。文件完整路径=basePath+directory
     * @param basePath  服务器的基础路径 
     * @param directory  上传到该目录  
     * @param sftpFileName  sftp端文件名
     * @param input   输入流
     */
    public void upload(String basePath,String directory, String sftpFileName, InputStream input) throws SftpException{
        try {
            sftp.cd(basePath);
            sftp.cd(directory);
        } catch (SftpException e) {
            //目录不存在，则创建文件夹
            String [] dirs=directory.split("/");
            String tempPath=basePath;
            for(String dir:dirs){
                if(null== dir || "".equals(dir)) continue;
                tempPath+="/"+dir;
                try{
                    sftp.cd(tempPath);
                }catch(SftpException ex){
                    sftp.mkdir(tempPath);
                    sftp.cd(tempPath);
                }
            }
        }
        sftp.put(input, sftpFileName);  //上传文件
    }


    /**
     * 下载文件。
     * @param directory 下载目录  
     * @param downloadFile 下载的文件 
     * @param saveFile 存在本地的路径 
     */
    public void download(String directory, String downloadFile, String saveFile) throws SftpException, FileNotFoundException{
        if (directory != null && !"".equals(directory)) {
            sftp.cd(directory);
        }
        File file = new File(saveFile);
        sftp.get(downloadFile, new FileOutputStream(file));
    }

    /**
     * 下载文件 
     * @param directory 下载目录 
     * @param downloadFile 下载的文件名 
     * @return 字节数组
     */
    public byte[] download(String directory, String downloadFile) throws SftpException, IOException{
        if (directory != null && !"".equals(directory)) {
            sftp.cd(directory);
        }
        InputStream is = sftp.get(downloadFile);

        byte[] fileData = IOUtils.toByteArray(is);

        return fileData;
    }


    /**
     * 删除文件 
     * @param directory 要删除文件所在目录 
     * @param deleteFile 要删除的文件 
     */
    public void delete(String directory, String deleteFile) throws SftpException{
        sftp.cd(directory);
        sftp.rm(deleteFile);
    }


    /**
     * 列出目录下的文件 
     * @param directory 要列出的目录
     */
    public Vector<?> listFiles(String directory) throws SftpException {
        return sftp.ls(directory);
    }

    //上传文件测试
/*   public static void main(String[] args) throws SftpException, IOException {
        SftpUtil sftp = new SftpUtil("cardezu", "!@#cardezu123", "47.99.78.122", 22);
        sftp.login();
        sftp.download("/mnt/sftpfile/um","back_20190730.txt","/mnt/txt001");
        //File file = new File("D:\\图片\\t0124dd095ceb042322.jpg");
//        InputStream is = new FileInputStream(file);
//
//        sftp.upload("基础路径","文件路径", "test_sftp.jpg", is);
        sftp.logout();
    }*/

   /* public Map<String,String> read(String fileUid, String folderName) throws Exception {
        SftpUtil sftp = new SftpUtil("cardezu", "!@#cardezu123", "47.99.78.122", 22);
        ByteArrayOutputStream writer = null;
        Map<String,String> pojo = new HashMap<>();

        try {
            sftp.cd(folderName);

            writer = new ByteArrayOutputStream();
            sftp.get(new String(fileUid.getBytes("UTF-8"), "ISO-8859-1"), writer);

            byte[] content = writer.toByteArray();

           *//* pojo = new FilePoJo();
            pojo.setName(getFileName(fileUid));
            pojo.setUuid(fileUid);
            pojo.setContent(content);
            pojo.setExtendName(getExtendName(fileUid));*//*

        }
        catch (SftpException e)
        {
            log.error("execute read(fileUid, folderName) function failure, pls check the parameters of fileUid and folderName!");
            throw e;
        }
        finally
        {
            if(writer != null)
            {
                writer.close();
            }
            sftp.logout();
        }

        return pojo;
    }*/


    /**
     * 从SFTP服务器下载文件
     * @param ftpHost SFTP IP地址
     * @param ftpUserName SFTP 用户名
     * @param ftpPassword SFTP用户名密码
     * @param ftpPort SFTP端口
     * @param ftpPath SFTP服务器中文件所在路径 格式： ftptest/aa
     */
    public static void downloadSftpFile(String ftpHost, String ftpUserName,String ftpPassword, int ftpPort, String ftpPath) throws JSchException {

        Session session = null;
        Channel channel = null;

        JSch jsch = new JSch();
        session = jsch.getSession(ftpUserName, ftpHost, ftpPort);
        session.setPassword(ftpPassword);
        session.setTimeout(100000);
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
        if(!session.isConnected()){
            session.connect();
        }
        channel = session.openChannel("sftp");
        if(!channel.isConnected()){
            channel.connect();
        }
        ChannelSftp chSftp = (ChannelSftp) channel;
        try {
            InputStream inputStream = chSftp.get(ftpPath);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
            String line = null;
            while((line = bufferedReader.readLine()) != null){
            	System.out.println(line);
                //Pos订单保存
//                PosOrder posOrder = new PosOrder();
                String []info = line.split("\\|");
                if(info != null && info.length>5){
                    //查看 订单是否在系统已经存在 如果存在 就跳过
//                    PosOrder posOrderOnly = new PosOrder().setOrdId(info[0]).queryFirst();
//                    if(null != posOrderOnly){
//                        continue;
//                    }
//                    posOrder.setOrdId(info[0]);
//                    posOrder.setOrdAmount(BigDecimal.valueOf(Long.parseLong(info[1])).divide(new BigDecimal(100)).setScale(2));
//                    posOrder.setOrdFee(BigDecimal.valueOf(Long.parseLong(info[2])).divide(new BigDecimal(100)).setScale(2));
//                    posOrder.setOrdType(info[3]);
//                    posOrder.setCardType(info[4]);
//                    posOrder.setStlType(info[5]);
                    String merId = info[6];
                    //通过 U米的商户号获得 相关的用户信息  merId
//                    MerchantUmMapping umMapping = new MerchantUmMapping().setUmMerId(merId).queryFirst();
//                    if(null != umMapping){
//                        posOrder.setMerchantId(umMapping.getMerchantId());
//                        posOrder.setOwerAgentId(umMapping.getAgentId());
//                    }
//                    posOrder.setMerId(merId);
//                    posOrder.setMerName(info[7]);
//                    posOrder.setMerPro(info[8]);
//                    posOrder.setMerCity(info[9]);
//                    posOrder.setTermId(info[10]);
//                    posOrder.setOrdTime(DateTimeUtils.getDateTimeTwo(info[11]));
//                    posOrder.setOrdSts(info[12]);
//                    posOrder.setOrdDetail(info[13]);
//                    posOrder.setAgentId(info[14]);
//                    posOrder.setOtherFee(BigDecimal.valueOf(Long.parseLong(info[15])).divide(new BigDecimal(100)).setScale(2));
//                    posOrder.setSelFee(BigDecimal.valueOf(Long.parseLong(info[16])).divide(new BigDecimal(100)).setScale(2));
//                    posOrder.setOrderNo("UMPO"+IDUtils.commonOrderNo());
//                    posOrder.setCreateTime(new Date());
//                    posOrder.setUpdateTime(new Date());
//                    posOrder.save();
                }
            }

        } catch (Exception e) {
        } finally {
            //关闭持久连接  谨慎使用  详细见下面说明
            chSftp.quit();
            channel.disconnect();
            session.disconnect();
        }

    }

    /**
     * 上传单个文件
     *
     * @param directory  上传到sftp目录
     * @param uploadFile 要上传的文件,包括路径
     * @throws Exception
     */
    public void upload(String directory, String uploadFile) throws Exception {
        login();

        InputStream in = sftp.get(uploadFile);
        try {

            upload(directory, "12311.txt", in);
        } catch (Exception ex) {
            if (in != null) {
                in.close();
            }
            ex.printStackTrace();
        }finally {
            in.close();
            logout();
        }
    }



    /**
     * 将输入流的数据上传到sftp作为文件
     *
     * @param directory    上传到该目录
     * @param sftpFileName sftp端文件名
     * @param input        输入流
     * @throws Exception
     */
    public void upload(String directory, String sftpFileName, InputStream input) throws Exception {
        try {
            try {// 如果cd报异常，说明目录不存在，就创建目录
                sftp.cd(directory);
            } catch (Exception e) {
                sftp.mkdir(directory);
                sftp.cd(directory);
            }
            sftp.put(input, sftpFileName);
//            log.info("SFTP上传成功！文件名：" + sftpFileName);
        } catch (Exception e) {
//            log.error("SFTP上传失败！文件名" + sftpFileName, e);
            throw e;
        }finally {
            input.close();
            logout();
        }
    }


    /**
     * 将输入流的数据上传到sftp作为文件。文件完整路径=basePath+directory
     * @param basePath  服务器的基础路径
     * @param directory  上传到该目录
     * @param sftpFileName  sftp端文件名
     * @param commonFile   通用文件路径
     */
    public void upload(String basePath,String directory, String sftpFileName, String commonFile) throws SftpException{
        login();
//        InputStream input = null;
        try {
            sftp.cd(basePath);
            sftp.cd(directory);
        } catch (SftpException e) {
            //目录不存在，则创建文件夹
            String [] dirs=directory.split("/");
            String tempPath=basePath;
            for(String dir:dirs){
                if(null== dir || "".equals(dir)) continue;
                tempPath+="/"+dir;
                try{
                    sftp.cd(tempPath);
                }catch(SftpException ex){
                    sftp.mkdir(tempPath);
                    sftp.cd(tempPath);
                }
            }
        }
//        input = sftp.get(commonFile);
//        sftp.put(input, sftpFileName);  //上传文件
        sftp.put(commonFile,basePath+directory,sftp.OVERWRITE);
        logout();
    }


    /**
     * �����ļ�
     *
     * @param key
     *            ��Կ
     * @param plainFilePath
     *            明文
     * @param secretFilePath
     *            密文
     * @throws Exception
     */
    public String decodeAESFile(byte[] key, String plainFilePath,String fileName,String secretFilePath) throws Exception {
        String sftpPath="";
        login();
        InputStream fis = null;
        ByteArrayOutputStream bos = null;
        OutputStream fos = null;
        try {
            fis = sftp.get(secretFilePath);
//			fis.
            bos = new ByteArrayOutputStream(fis.available());

            byte[] buffer = new byte[1024];
            int count = 0;
            while ((count = fis.read(buffer)) != -1) {
                bos.write(buffer, 0, count);
            }
            bos.flush();

            byte[] bytes = DESUtil.decodeAES(key, bos.toByteArray());
            String sftpCd = sftp.pwd();
            sftpPath = sftpCd+plainFilePath+fileName;
            fos  = sftp.put(sftpPath);
            fos.write(bytes);
            fos.flush();

        } catch (Exception e) {
            throw e;
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (Exception e) {
//                    log.error(e.getLocalizedMessage(), e);
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (Exception e) {
//                    log.error(e.getLocalizedMessage(), e);
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (Exception e) {
//                    log.error(e.getLocalizedMessage(), e);
                }
            }
            logout();
        }
        return sftpPath;
    }

    /**
     * 从SFTP服务器传到七牛云
     * @param ftpFilePath SFTP服务器中文件所在路径 格式： /xxx/xxx.xxx
     * @param qiniuFileAllName 要上传到七牛上面的文件全名，格式：xxx/xxx.xxx
     * @return qiniuFileAllName 若失败，返回null
     */
    public String downloadSftpFileAndUploadToQiniu(String ftpFilePath, String qiniuFileAllName) throws JSchException {
    	String reStr = null;
        login();
        InputStream inputStream = null;
        try {
            inputStream = sftp.get(ftpFilePath);
    		
			byte[] data = IOUtils.toByteArray(inputStream);
			reStr = new QiniuCloudUtil().uploadToQiniu(data, qiniuFileAllName);
        } catch (Exception e) {
        } finally {
            //关闭持久连接  谨慎使用  详细见下面说明
            logout();
        }
        return reStr;
    }

    /**
     * 从SFTP服务器下载文件
     * @param ftpFilePath SFTP服务器中文件所在路径 格式： /xxx/xxx.xxx
     * @return InputStream 若失败，返回null
     */
    public String downloadSftpFileAndDecode(String ftpFilePath, String key) throws JSchException {
    	String reStr = null;
        login();
        InputStream inputStream = null;
        try {
            inputStream = sftp.get(ftpFilePath);
            
    		ByteArrayOutputStream bos = null;
    		try {
    			bos = new ByteArrayOutputStream(inputStream.available());

    			byte[] buffer = new byte[1024];
    			int count = 0;
    			while ((count = inputStream.read(buffer)) != -1) {
    				bos.write(buffer, 0, count);
    			}
    			bos.flush();

    			byte[] bytes = DESUtil.decodeAES(key.getBytes(), bos.toByteArray());
    			reStr =  new String(bytes, "utf-8");

    		} catch (Exception e) {
    			throw e;
    		}
        } catch (Exception e) {
        } finally {
            //关闭持久连接  谨慎使用  详细见下面说明
            logout();
        }
        return reStr;
    }

    /**
     * 从SFTP服务器传到七牛云
     * @param ftpFileName SFTP服务器中文件全路径 格式： /xxx/xxx.xxx
     */
    public void removeSftpFile(String ftpFileName) throws JSchException {
        login();
        try {
        	SftpATTRS attrs = sftp.stat(ftpFileName);
            sftp.rm(ftpFileName);
        } catch (Exception e) {
        	e.printStackTrace();
			System.out.println("不存在");
        } finally {
            //关闭持久连接  谨慎使用  详细见下面说明
            logout();
        }
    }

    /**
     * 从SFTP服务器传到七牛云
     * @param ftpDirName SFTP服务器中目录路径，格式： /xxx/xxx
     */
    public String removeSftpDir(String ftpDirName) throws JSchException {
    	String reStr = null;
        login();
        try {
        	SftpATTRS attrs = sftp.lstat(ftpDirName);
            sftp.rmdir(ftpDirName);
        } catch (Exception e) {
        	e.printStackTrace();
        } finally {
            //关闭持久连接  谨慎使用  详细见下面说明
            logout();
        }
        return reStr;
    }

    /**
     * 从SFTP服务器下载文件
     * @param ftpFilePath SFTP服务器中文件所在路径 格式： /xxx/xxx.xxx
     * @return InputStream 若失败，返回null
     */
    public void test() throws JSchException {
        login();
        try {
			sftp.rmdir("/upload/upload/DBQ/02/ord/201911221030");
		} catch (SftpException e) {
			e.printStackTrace();
		} finally {
	        //关闭持久连接  谨慎使用  详细见下面说明
	        logout();
		}
    }

    /**
     * 从SFTP服务器下载文件
     * @param ftpDirPath SFTP服务器中文件所在路径 格式： /xxx/xxx.xxx
     * @return InputStream 若失败，返回null
     */
    public List<String> listFile(String ftpDirPath) throws JSchException {
    	List<String> listStr = new ArrayList<String>();
        login();
        try {
			Vector vector = sftp.ls(ftpDirPath);
			int i = 0;
			for(Object obj :vector){
                if(obj instanceof LsEntry){
                    String fileName = ((LsEntry)obj).getFilename();
                    if (!fileName.startsWith("ord_2020") && !fileName.startsWith("2020")) {
						continue;
					}
                    if (!fileName.contains(".")) {
                    	String ftpDirPathSub = ftpDirPath + "/" + fileName;
                    	
            			Vector vectorSub = sftp.ls(ftpDirPathSub);
            			for(Object objSub :vectorSub){
                            if(objSub instanceof LsEntry){
                                String fileNameSub = ((LsEntry)objSub).getFilename();
                                if (fileNameSub.contains(".")) {
            						if (!".".equals(fileNameSub) && !"..".equals(fileNameSub)) {
                	                    listStr.add(ftpDirPathSub + "/" + fileNameSub);
            						}
            					}
                            }
                        }
					} else {
						if (!".".equals(fileName) && !"..".equals(fileName)) {
		                    listStr.add(ftpDirPath + "/" + fileName);
						}
					}
                }
                
    			if (i > 50) {
    				break;
    			}
            }
			i++;
		} catch (SftpException e) {
			e.printStackTrace();
		} finally {
	        //关闭持久连接  谨慎使用  详细见下面说明
	        logout();
		}
        return listStr;
    }


    /**
     * 从SFTP服务器下载文件
     * @param ftpPath SFTP服务器中文件所在路径 格式： ftptest/aa
     */
    public void downloadSftpDayFile( String ftpPath) throws JSchException {
        login();
        try {
            InputStream inputStream = sftp.get(ftpPath);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
            String line = null;
            String ordId = null;
            while((line = bufferedReader.readLine()) != null){
                String []info = line.split("\\|");
                System.out.println("-----------");
                if(info != null && info.length>5){
                	for(String str : info) {
                		System.out.println(str);
                	}
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭持久连接  谨慎使用  详细见下面说明
            logout();
        }

    }

    public void inputstreamtofile(InputStream ins,File file) throws IOException {
        OutputStream os = new FileOutputStream(file);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        os.close();
        ins.close();
    }

    public static void main(String []args) {

        String sftpHost = "47.99.78.122";
        String sftpPort = "22";
//        String sftpUserName = "cardezu";
//        String sftpPassword = "!@#cardezu123";
        String sftpUserName = "root";
        String sftpPassword = "!QAZ1234@wsx#$";
        String sftpDefaultFile = "/upload/upload/DBQ/02/ord";
        String sftpPath = sftpDefaultFile + "/202004170900/ord_202004170900.txt";
        String aesKey = "YAmVxyQ#49s$N8bk";
        
        try {
            SftpUtil sftpUtil = new SftpUtil(sftpUserName, sftpPassword, sftpHost, Integer.valueOf(sftpPort));
//            String textDecoded = sftpUtil.downloadSftpFileAndDecode(sftpPath, aesKey);
            
//            sftpUtil.test();
//            List<String> listStr = sftpUtil.listFile("/upload/upload/DBQ/02/ord");
//            sftpUtil.removeSftpFile("/upload/upload/DBQ/02/ord/202001241730/ord_202001241730.txt");
//            sftpUtil.removeSftpFile(sftpPath);
            sftpUtil.removeSftpDir("/upload/upload/DBQ/02/ord/202004170900");
        } catch (JSchException e) {
            e.printStackTrace();
        } catch (Exception e) {
			e.printStackTrace();
		}

    }


}
